/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package Wires.impl;

import java.io.File;
import java.util.UUID;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.m2m.atl.engine.AtlEMFModelHandler;
import org.eclipse.m2m.atl.engine.vm.nativelib.ASMModel;

import Wires.AtomicModelTransformation;
import Wires.BasicData;
import Wires.CompositeTransformation;
import Wires.ConnectableElement;
import Wires.DecisionNode;
import Wires.GenericTransformation;
import Wires.IdentityTransformation;
import Wires.InputActualParameter;
import Wires.InputFormalParameter;
import Wires.Model;
import Wires.OutputActualParameter;
import Wires.Transformation;
import Wires.WiresPackage;
import Wires.exep.ResourceNotFoundException;
import Wires.exep.TypeNotFoundException;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Input Actual Parameter</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * </p>
 *
 * @generated
 */
public class InputActualParameterImpl extends ActualParameterImpl implements InputActualParameter {
	/***************************************************/
	/***************** Modifications *******************/
	
	private Boolean active = false;
		
	public void setActive(Boolean active) {
		this.active = active;
	}

	public Boolean getActive() {
		return active;
	}	
				
	public void loadModel(){
		if (this.getType() == null)
			throw new TypeNotFoundException(this);
		String modelName = ((InputFormalParameter)this.getType()).getName();
		AtlEMFModelHandler modelHandler = (AtlEMFModelHandler) AtlEMFModelHandler.getDefault(AtlEMFModelHandler.AMH_EMF);
		this.model =  modelHandler.loadModel(modelName, this.metamodel, URI.createFileURI(this.modelPath));		
	}
	
	public void execute(ConnectableElement incoming) throws Exception{		
		//Prepare the parameter with the incoming data
		if (incoming instanceof Model){
			
			if (((Model)incoming).getPath()==null)
				throw new ResourceNotFoundException(incoming);
				
			//Save the model path
			this.modelPath = ((Model)incoming).getPath();
			
			File f = new File(modelPath);
			if (!f.exists()) {
				throw new ResourceNotFoundException(incoming);
			}
			
			//Load the model
			if (!(this.eContainer() instanceof IdentityTransformation)){
				this.loadMetamodel();
				this.loadModel();
			}
			
		}else if (incoming instanceof BasicData){
			//Store the basic value of the BasicData
			this.setBasicDataValue(((BasicDataImpl)incoming).getValue());
			
		}else if (incoming instanceof OutputActualParameter && !(this.eContainer() instanceof DecisionNode) ){
			
			if (((OutputActualParameter) incoming).eContainer() instanceof AtomicModelTransformation ||
				((OutputActualParameter) incoming).eContainer() instanceof GenericTransformation){
				
				this.copyASMModel(((OutputActualParameterImpl)incoming).getModel());
								
			}else if (((OutputActualParameter) incoming).eContainer() instanceof CompositeTransformation){				
				//Check if the incoming OutputParameter contains a BasicData or a model
				if (((OutputActualParameterImpl)incoming).basicDataValue == null){
					//The incoming parameter contains a Model
					this.copyASMModel(((OutputActualParameterImpl)incoming).getModel());					
				}else{
					//The incoming parameter contains a BasicData
					this.setBasicDataValue(((OutputActualParameterImpl)incoming).getBasicDataValue());
				}
				
			}else if (((OutputActualParameter) incoming).eContainer() instanceof IdentityTransformation){				
				//Copy the model path of the incoming OutputParameter
				this.setModelPath(((OutputActualParameterImpl)incoming).getModelPath());
			}
		}else if (incoming instanceof OutputActualParameter && (this.eContainer() instanceof DecisionNode) ){
			//Save the basic data value of the output parameter				
			this.setBasicDataValue(((OutputActualParameterImpl)incoming).getBasicDataValue());
			
		}else if (incoming instanceof InputFormalParameter && !(this.eContainer() instanceof IdentityTransformation)){
			
			// In the next case the input parameter metamodel is undefined, so it's taken from the InputFormalParameter Metamodel
			if (((InputFormalParameter)this.getType()).getTypeEl() == null){
				// Firstly the model path is loaded from the InputFormalParameter Model
				AtlEMFModelHandler modelHandler = (AtlEMFModelHandler) AtlEMFModelHandler.getDefault(AtlEMFModelHandler.AMH_EMF);
				modelHandler.saveModel(((InputFormalParameterImpl)incoming).getModel(), ((InputFormalParameterImpl)incoming).getModel().getName(), false);
				this.modelPath = ((InputFormalParameterImpl)incoming).getModel().getName();
				
				File f = new File(((InputFormalParameterImpl)incoming).getModel().getName());
				f.delete();
				
				// Secondly the metamodel is loaded using the same metamodel stored in the InputFormalParameter
				modelHandler.saveModel(((InputFormalParameterImpl)incoming).getMetamodel(), ((InputFormalParameterImpl)incoming).getMetamodel().getName(), false);				
				URI metamodelResource = null;								
				metamodelResource = URI.createFileURI(((InputFormalParameterImpl)incoming).getMetamodel().getName());
				String mmName = ((InputFormalParameterImpl)incoming).getMetamodel().getName();		
				this.metamodel = modelHandler.loadModel(mmName, modelHandler.getMof(), metamodelResource);
				
				File f2 = new File(((InputFormalParameterImpl)incoming).getMetamodel().getName());
				f2.delete();				
				
				// Finally the model is loaded
				this.loadModel();							
			}else{			
				this.copyASMModel(((InputFormalParameterImpl)incoming).getModel());
			}
		}else if (incoming instanceof InputFormalParameter && (this.eContainer() instanceof IdentityTransformation)){			
			if (((InputFormalParameterImpl)incoming).getModelPath() == null){		
				AtlEMFModelHandler modelHandler = (AtlEMFModelHandler) AtlEMFModelHandler.getDefault(AtlEMFModelHandler.AMH_EMF);
				modelHandler.saveModel(((InputFormalParameterImpl)incoming).getModel(), ((InputFormalParameterImpl)incoming).getModel().getName(), false);
				this.modelPath = ((InputFormalParameterImpl)incoming).getModel().getName();
			}else{
				this.modelPath = ((InputFormalParameterImpl)incoming).getModelPath();
			}			
		}
		
		this.setActive(true);
		if (this.eContainer() instanceof Transformation){
			((ConnectableElementImpl)this.eContainer()).execute(incoming);
		}else if (this.eContainer() instanceof DecisionNode){
			((DecisionNodeImpl)this.eContainer()).execute(incoming);
		}				
	}
	
	private void copyASMModel(ASMModel model){
		//Copy the out parameter model on this input parameter
//		AtlEMFModelHandler modelHandler = (AtlEMFModelHandler) AtlEMFModelHandler.getDefault(AtlEMFModelHandler.AMH_EMF);
//		modelHandler.saveModel(model, model.getName(), false);
//		this.modelPath = model.getName();	
		
		String name = "tmp" + UUID.randomUUID().toString();
		AtlEMFModelHandler modelHandler = (AtlEMFModelHandler)AtlEMFModelHandler.getDefault("EMF");
		modelHandler.saveModel(model, name, false);
		this.modelPath = name;

		
		this.loadMetamodel();
		this.loadModel();		
		
//		File f = new File(model.getName());
		File f = new File(name);
		f.delete();
	}
	
	
	/**************** Modifications End ****************/
	/***************************************************/
	
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected InputActualParameterImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return WiresPackage.Literals.INPUT_ACTUAL_PARAMETER;
	}

} //InputActualParameterImpl
